package org.apli.haiam.admin.jsf.managed;

import com.apli.controladores.AplinfoFactoryBean;
import java.util.*;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.apli.haiam.admin.entidades.UsuarioAdmin;
import org.apli.haiam.ejb.entidades.AdmAccion;
import org.apli.haiam.ejb.entidades.AdmMenu;
import org.apli.haiam.ejb.entidades.AdmSistema;
import org.apli.haiam.ejb.interfaces.AdministradorLoginHaiam;
import org.apli.haiam.ejb.interfaces.AdministradorPerfilHaiam;
import org.apli.jsf.managed.JsfBean;
import org.richfaces.ui.iteration.tree.TreeSelectionChangeEvent;
import org.richfaces.ui.iteration.tree.UITree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Clase backing Bean que administra la entidad AdmMenu.
 * <p>
 * <H6>Soporte:HAIAM
 * <I>david_s_1086@hotmail.com,david.carranza@haiam.gob.ec</I></H6>
 *
 * @author david Carranza
 * @version 1.0 30/07/2014
 */
@ManagedBean
@ViewScoped
public class JsfMenu extends JsfBean<AdmMenu> {

    @EJB
    private AdministradorPerfilHaiam adminPerfil;
    @EJB
    private AdministradorLoginHaiam adminLogin;
    final Logger log = LoggerFactory.getLogger(JsfMenu.class);
    private List<AdmMenu> menusAsignados;
    private List<AdmMenu> menusNoAsignados;
    private List<AdmMenu> menuPrincipal;
    private List<AdmAccion> accionesAsignados;
    private List<AdmAccion> accionesNoAsignados;
    private AdmMenu objSeleccionado;
    private AdmMenu menuSelecionadoAccion;
    private AdmSistema sistemaSeleccionado;
    private int asignado;

    /**
     * Constructor por defecto.
     */
    public JsfMenu() {
    }

    /**
     * Inicializa los datos miembros.
     */
    @Override
    protected void inicializar() {
        try {
            sistemaSeleccionado = (AdmSistema) admin.buscar(AdmSistema.class, "clave", "HAIAM");
        } catch (Exception ex) {
            log.error("" + ex);
        }

        cargarEjb();
        object = new AdmMenu();
        object.setObligatorio((short) 1);
        object.setVisible((short) 1);
        object.setSecuencia((short) 0);
        cargarLista();
        sistemaSelectionListener();

    }

    /**
     * Graba el registro asociado al objeto que se administra en la página.
     *
     * @return null, se mantiene en la página invocada.
     */
    @Override
    public String grabarAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        if (object.getIdMenu() == null) {
            try {
                if (!admin.existePorCampo(object.getClass(), "clave", object.getNombre())) {
                    admin.crear(object, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
                    inicializar();
                    cargarTreeRoot();
                    FacesContext.getCurrentInstance().addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(bundle.getString("msg.grabar")));
                } else {
                    FacesContext.getCurrentInstance().addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, "Clave ya existe", "Clave ya existe"));
                }
            } catch (Exception e) {
                log.error("grabarAction() {} ", e.getMessage());
                FacesContext.getCurrentInstance().addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
            }
        } else {
            try {
                admin.modificar(object, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
                FacesContext.getCurrentInstance().addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(bundle.getString("msg.actualizar")));
                cargarLista();
                cargarTreeRoot();
            } catch (Exception e) {
                log.error("grabarAction() {} ", e.getMessage());
                FacesContext.getCurrentInstance().addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
            }
        }
        return null;
    }

    public String grabarMenuAction() {
        FacesContext context = FacesContext.getCurrentInstance();

        try {
            menuSelecionadoAccion.setAdmAccionList(accionesAsignados);
            admin.modificar(menuSelecionadoAccion, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
            context.addMessage(findComponent(context.getViewRoot(), "pickList1").getClientId(), new FacesMessage(bundle.getString("msg.actualizar")));
            cargarAcciones();
        } catch (Exception e) {
            log.error("grabarAction() {} ", e.getMessage());
            FacesContext.getCurrentInstance().addMessage(findComponent(context.getViewRoot(), "formAcciones").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
        }

        return null;
    }

    /**
     * Obtiene una lista de objetos de tipo SelectedItem.
     *
     * @return la lista
     */
    @Override
    public List<SelectItem> getSelectedItem() {
        try {
            List<AdmMenu> datos = admin.listarOrdenada(object.getClass(), "nombre", true);
            List<SelectItem> items = new ArrayList<>();
            for (AdmMenu obj : datos) {
                items.add(new SelectItem(obj, obj.getNombre()));
            }
            return items;
        } catch (Exception e) {
            log.error("getSelectedItem() {} ", e.getMessage());
        }
        return null;
    }

    public List<AdmMenu> getTreeRoot() {
        if (menuPrincipal == null) {
            cargarTreeRoot();
        }
        return menuPrincipal;
    }

    private void cargarTreeRoot() {
        if (admin == null) {
            return;
        }
        try {
            menuPrincipal = admin.listarNullOrdenada(object.getClass(), "admMenu", "secuencia", true);
            if (menuPrincipal != null) {
                for (AdmMenu dmpMenu0 : menuPrincipal) {
                    dmpMenu0.setAdmMenuList(getSubmenu(dmpMenu0));
                }
            }
        } catch (Exception e) {
            log.error("getTreeRoot() {} ", e.getMessage());
        }
    }

    private List<AdmMenu> getSubmenu(AdmMenu menu) throws Exception {
        List<AdmMenu> datos = admin.listarOrdenada(AdmMenu.class, "admMenu", menu, "secuencia", true);
        menu.setAdmMenuList(datos);
        if (datos == null || datos.isEmpty()) {
            return null;
        }
        for (AdmMenu mm : datos) {
            mm.setAdmMenuList(getSubmenu(mm));
        }
        return datos;
    }

    public List<AdmMenu> getTreeRootMenuAsignados() {
        cargarTreeRootMenuAsignados();
        return menusAsignados;
    }

    private void cargarTreeRootMenuAsignados() {
        if (adminLogin == null) {
            cargarEjb();
        }
        try {
            menusAsignados = adminLogin.getMenuPorSistemaAsignados(sistemaSeleccionado);
        } catch (Exception e) {
            log.error("getTreeRoot() {} ", e.getMessage());
        }
    }

    public List<AdmMenu> getTreeRootMenuNoAsignados() {
        cargarTreeRootMenuNoAsignados();
        return menusNoAsignados;
    }

    private void cargarTreeRootMenuNoAsignados() {
        if (adminLogin == null) {
            cargarEjb();
        }
        try {
            menusNoAsignados = adminLogin.getMenusPorSistemaNoAsignados(sistemaSeleccionado);
        } catch (Exception e) {
            log.error("getTreeRoot() {} ", e.getMessage());
        }
    }

//    private void selectionListener(TreeSelectionEvent event) {
//
//        System.out.println(event);
//
//    }
    public void selectionChanged(TreeSelectionChangeEvent event) {
        List<Object> selection = new ArrayList<>(event.getNewSelection());
        Object currentSelectionKey = selection.get(0);
        UITree tree = (UITree) event.getSource();
        Object storedKey = tree.getRowKey();
        tree.setRowKey(currentSelectionKey);
        object = (AdmMenu) tree.getRowData();
//        System.out.println(object);
        tree.setRowKey(storedKey);
    }

    public void selectionChangedAcciones(TreeSelectionChangeEvent event) {
        List<Object> selection = new ArrayList<>(event.getNewSelection());
        Object currentSelectionKey = selection.get(0);
        UITree tree = (UITree) event.getSource();
        Object storedKey = tree.getRowKey();
        tree.setRowKey(currentSelectionKey);
        menuSelecionadoAccion = (AdmMenu) tree.getRowData();
//        System.out.println(object);
        tree.setRowKey(storedKey);
        cargarAcciones();
    }

    public void selectionChangedAsignado(TreeSelectionChangeEvent event) {
        List<Object> selection = new ArrayList<>(event.getNewSelection());
        Object currentSelectionKey = selection.get(0);
        UITree tree = (UITree) event.getSource();
        Object storedKey = tree.getRowKey();
        tree.setRowKey(currentSelectionKey);
        objSeleccionado = (AdmMenu) tree.getRowData();
//        System.out.println(objSeleccionado);
        tree.setRowKey(storedKey);
        asignado = 1;
    }

    public void selectionChangedNoAsignado(TreeSelectionChangeEvent event) {
        List<Object> selection = new ArrayList<>(event.getNewSelection());
        Object currentSelectionKey = selection.get(0);
        UITree tree = (UITree) event.getSource();
        Object storedKey = tree.getRowKey();
        tree.setRowKey(currentSelectionKey);
        objSeleccionado = (AdmMenu) tree.getRowData();
//        System.out.println(objSeleccionado);
        tree.setRowKey(storedKey);
        asignado = 2;
    }

//    public void selectionNode(javax.faces.event.AjaxBehaviorEvent event) {
////        UITree ui = (UITree)event;
////        ui.getData();
//        UITree tree = (UITree) event.getSource();
//        System.out.println(event.getComponent());
//        Object storedKey = tree.getRowKey();
//    }
//    public String selectionNode(Object event) {
//        System.out.println(event);
//        return null;
//    }
//
//    public TreeNode getCurrentSelection() {
//        System.out.println(currentSelection);
//        return currentSelection;
//    }
//
//    public void setCurrentSelection(TreeNode currentSelection) {
//        System.out.println(currentSelection);
//        this.currentSelection = currentSelection;
//    }
    public void sistemaSelectionListener() {
        asignado = 3;
        objSeleccionado = null;
    }

    public void asignadosSelectionListener() {
        asignado = 1;
    }

    public void eliminarMenuButtonListener() {
        FacesContext context = FacesContext.getCurrentInstance();
        if (objSeleccionado != null) {

            Map<String, AdmMenu> menus = getMenus(menusAsignados);
            Map<String, AdmMenu> menusEliminar = new HashMap<>();
            //menus.remove(objSeleccionado.getClave());
            agregarMenuUp(objSeleccionado, menusEliminar);
            Collection<AdmMenu> dd = menusEliminar.values();
            for (AdmMenu oo : dd) {
                menus.remove(oo.getClave());
            }
            List<AdmMenu> datos = new ArrayList<>();
            for (AdmMenu obj : menus.values()) {
                datos.add(obj);
            }
            sistemaSeleccionado.setAdmMenuList(datos);
            try {
                adminPerfil.eliminarMenuSistema(sistemaSeleccionado, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
                log.info("asignadosButtonListener() {} ", "Registro grabado correctamente");
            } catch (Exception e) {
                log.error("asignadosButtonListener() {} ", e.getMessage());
                context.addMessage(findComponent(context.getViewRoot(), "arbolForm").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
            }
            cargarTreeRootMenuAsignados();
            cargarTreeRootMenuNoAsignados();
        }
    }

    public void agregarMenuButtonListener() {
        FacesContext context = FacesContext.getCurrentInstance();
        if (objSeleccionado != null) {
            Map<String, AdmMenu> menus = getMenus(menusAsignados);
            agregarMenuDown(objSeleccionado, menus);
            agregarMenuUp(objSeleccionado, menus);
            List<AdmMenu> datos = new ArrayList<>();
            for (AdmMenu obj : menus.values()) {
                datos.add(obj);
            }
            sistemaSeleccionado.setAdmMenuList(datos);
            try {
                adminPerfil.asignarMenuSistema(sistemaSeleccionado, (UsuarioAdmin) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));
                log.info("agregarMenuButtonListener() {} ", "Registro grabado correctamente");
            } catch (Exception e) {
                log.info("agregarMenuButtonListener() {} ", "Registro grabado correctamente");
                context.addMessage(findComponent(context.getViewRoot(), "arbolForm").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
            }
            cargarTreeRootMenuAsignados();
            cargarTreeRootMenuNoAsignados();
        }
    }

    private Map<String, AdmMenu> getMenus(List<AdmMenu> lista) {
        Map<String, AdmMenu> menus = new HashMap<>();
        if (lista != null) {
            for (AdmMenu obj : lista) {
                agregarMenuUp(obj, menus);
            }
        }
        return menus;
    }

    private void agregarMenuUp(AdmMenu obj, Map<String, AdmMenu> datosMenus) {
        if (obj != null) {
            datosMenus.put(obj.getClave(), obj);
            if (obj.getAdmMenuList() != null) {
                for (AdmMenu obj1 : obj.getAdmMenuList()) {
                    agregarMenuUp(obj1, datosMenus);
                }
            }
        }
    }

    private void agregarMenuDown(AdmMenu obj, Map<String, AdmMenu> datosMenus) {
        if (obj != null) {
            datosMenus.put(obj.getClave(), obj);
            if (obj.getAdmMenu() != null) {
                agregarMenuDown(obj.getAdmMenu(), datosMenus);
            }
        }
    }

    public void noAsignadosSelectionListener() {
        asignado = 2;
    }
////    public void selectionChanged(TreeSelectionChangeEvent selectionChangeEvent) {
////        // considering only single selection
////        List<Object> selection = new ArrayList<Object>(selectionChangeEvent.getNewSelection());
////        Object currentSelectionKey = selection.get(0);
////        UITree tree = (UITree) selectionChangeEvent.getSource();
////
////        Object storedKey = tree.getRowKey();
////        tree.setRowKey(currentSelectionKey);
////        currentSelection = (TreeNode) tree.getRowData();
////        tree.setRowKey(storedKey);
////    }

    public boolean isVisible() {
        if (object == null || object.getVisible() == null) {
            return false;
        }
        return object.getVisible() == 1;
    }

    public void setVisible(boolean dato) {
        if (object == null) {
            return;
        }
        object.setVisible(dato ? (short) 1 : (short) 0);
    }

    public String eliminarAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            //DmpMenu _menu = object.getDmpMenu();
            admin.eliminar(object, FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user"));

            inicializar();
            cargarLista();
            cargarTreeRoot();
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(bundle.getString("msg.eliminar")));
        } catch (Exception e) {
            log.error("eliminarAction() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formDatos").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
        }
        return null;
    }

    public String nuevoMenuItemAction() {
        AdmMenu mm = object;
        inicializar();
        object.setAdmMenu(mm);
        object.setClave(mm.getClave() + ".");
        object.setNivel((short) 0);
        object.setObligatorio((short) 1);
        object.setVisible((short) 1);
        object.setAdmSistema(mm.getAdmSistema());
        if (mm.getAdmMenu() != null) {
            object.setNivel((short) 1);
            if (mm.getAdmMenu().getAdmMenu() != null) {
                object.setNivel((short) 2);
                if (mm.getAdmMenu().getAdmMenu().getAdmMenu() != null) {
                    object.setNivel((short) 3);
                }
            }
        }
        return null;
    }
//    public void cargarMenusPorSistema() {
//        FacesContext context = FacesContext.getCurrentInstance();
//        try {
//            if (sistema != null) {
//                menusAsignados = ((DmpSistema)adminObject.buscar(DmpSistema.class, sistema.getIdSistema())).getDmpMenuList();
//                menusNoAsignados = adminPerfil.getAccionesPorRolPorSistema(rol, sistema, 1);
//            }
//        } catch (Exception e) {
//            log.error("cargarAcciones() {} ", e.getMessage());
//            context.addMessage(findComponent(context.getViewRoot(), "formDatos2").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
//        }
//    }
//
//    public List<SelectItem> getSelectedItemMenusNoAsignadas() {
//        List<DmpMenu> datos = new ArrayList<DmpMenu>();
//        List<SelectItem> items = new ArrayList<SelectItem>();
//        try {
//            datos = accionesNoAsignados;
//            for (DmpMenu obj : datos) {
//                items.add(new SelectItem(obj, obj.getNombre()));
//            }
//            return items;
//        } catch (Exception e) {
//            log.error("getSelectedItem() {} ", e.getMessage());
//        }
//        return null;
//    }
//
//    public List<SelectItem> getSelectedItemMenusAsignadas() {
//        List<DmpMenu> datos = new ArrayList<DmpMenu>();
//        List<SelectItem> items = new ArrayList<SelectItem>();
//        try {
//            datos = accionesNoAsignados;
//            for (DmpMenu obj : datos) {
//                items.add(new SelectItem(obj, obj.getNombre()));
//            }
//            return items;
//        } catch (Exception e) {
//            log.error("getSelectedItem() {} ", e.getMessage());
//        }
//        return null;
//    }

    /**
     * Método optener conexión a EJB de Perfiles.
     */
    @Override
    protected void cargarEjb() {
        super.cargarEjb();
        if (adminPerfil == null) {
            String ejbPath = null;
            try {
                ResourceBundle property = getProperties();
                String ORBContext = property.getString("ORBContext");
                String ejbContextPath = property.getString("ejb.context.path.admin");
                ejbPath = ORBContext + ejbContextPath + "/AdministradorPerfilBeanHaiam";
                adminPerfil = (AdministradorPerfilHaiam) AplinfoFactoryBean.lookupBean(ejbPath, false);
//                try {
//                    admin.getFechaDb();
//                } catch (Exception e) {
//                }
            } catch (Exception e) {
                log.error("cargarEjbPerfil() {} - {} ", ejbPath, e.getMessage());
            }
        }
        if (adminLogin == null) {
            String ejbPath = null;
            try {
                ResourceBundle property = getProperties();
                String ORBContext = property.getString("ORBContext");
                String ejbContextPath = property.getString("ejb.context.path.admin");
                ejbPath = ORBContext + ejbContextPath + "/AdministradorLoginBeanHaiam";
                adminLogin = (AdministradorLoginHaiam) AplinfoFactoryBean.lookupBean(ejbPath, false);
//                try {
//                    adminLogin.getFechaDb();
//                } catch (Exception e) {
//                }
            } catch (Exception e) {
                log.error("cargarEjbLogin() {} - {} ", ejbPath, e.getMessage());
            }
        }
    }

    @Override
    protected ResourceBundle getProperties() {
        return ResourceBundle.getBundle("aplicacion");
    }

    public AdmSistema getSistemaSeleccionado() {
        return sistemaSeleccionado;
    }

    public void setSistemaSeleccionado(AdmSistema sistemaSeleccionado) {
        this.sistemaSeleccionado = sistemaSeleccionado;
    }

    public AdmMenu getObjSeleccionado() {
        return objSeleccionado;
    }

    public void setObjSeleccionado(AdmMenu objSeleccionado) {
        this.objSeleccionado = objSeleccionado;
    }

    public int getAsignado() {
        return asignado;
    }

    public void setAsignado(int asignado) {
        this.asignado = asignado;
    }

    public List<SelectItem> getSelectedItemAccionesNoAsignadas() {
        List<AdmAccion> datos;
        List<SelectItem> items = new ArrayList<SelectItem>();
        try {
            if (accionesNoAsignados != null) {
                datos = accionesNoAsignados;
                for (AdmAccion obj : datos) {
                    items.add(new SelectItem(obj, obj.getNombre() + " (" + obj.getClave() + ")"));
                }
                return items;
            }
        } catch (Exception e) {
            log.error("getSelectedItemAccionesNoAsignadas() {} ", e.getMessage());
        }
        return null;
    }

    public List<SelectItem> getSelectedItemAccionesAsignadas() {
        List<AdmAccion> datos;
        List<SelectItem> items = new ArrayList<SelectItem>();
        try {
            if (accionesAsignados != null) {
                datos = accionesAsignados;
                for (AdmAccion obj : datos) {
                    items.add(new SelectItem(obj, obj.getNombre() + " (" + obj.getClave() + ")"));
                }
                return items;
            }
        } catch (Exception e) {
            log.error("getSelectedItemAccionesAsignadas() {} ", e.getMessage());
        }
        return null;
    }

    public void cargarAcciones() {
        FacesContext context = FacesContext.getCurrentInstance();
        accionesAsignados = new ArrayList<AdmAccion>();
        accionesNoAsignados = new ArrayList<AdmAccion>();
        try {
            if (menuSelecionadoAccion != null && (menuSelecionadoAccion.getAdmMenuList() == null || menuSelecionadoAccion.getAdmMenuList().isEmpty())) {
                System.out.println(object.getNombre());
                accionesAsignados = adminPerfil.getAccionesPorMenuPorSistema(menuSelecionadoAccion, menuSelecionadoAccion.getAdmSistema(), 0);
                accionesNoAsignados = adminPerfil.getAccionesPorMenuPorSistema(menuSelecionadoAccion, menuSelecionadoAccion.getAdmSistema(), 1);
            }
        } catch (Exception e) {
            log.error("cargarAcciones() {} ", e.getMessage());
            context.addMessage(findComponent(context.getViewRoot(), "formAcciones").getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, e.toString(), e.getMessage()));
        }
    }

    public List<AdmAccion> getAccionesAsignados() {
        return accionesAsignados;
    }

    public void setAccionesAsignados(List<AdmAccion> accionesAsignados) {
        this.accionesAsignados = accionesAsignados;
    }
}
